package besta.moon.sql.expression.function.string;

import java.io.ByteArrayOutputStream;

import besta.moon.MoonException;
import besta.moon.MoonCode;
import besta.moon.sql.expression.function.FunctionReturnP1StringAndBinary;
import besta.moon.sql.parser.SQLTokenizer;

public class FunctionInsert extends FunctionReturnP1StringAndBinary {

    @Override
    public final int getFunction() {
        return SQLTokenizer.INSERT;
    }

    @Override
    public final boolean isNull() throws Exception {
        return param1.isNull() || param2.isNull() || param3.isNull() || param4.isNull();
    }

    @Override
    public final byte[] getBytes() throws Exception {
        if (isNull()) {
            return null;
        }
        byte[] bytes = param1.getBytes();
        int start = Math.min(Math.max(0, param2.getInt() - 1), bytes.length);
        int length = Math.min(param3.getInt(), bytes.length);
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        buffer.write(bytes, 0, start);
        buffer.write(param4.getBytes());
        if (length < 0) {
            throw MoonException.create(MoonCode.INSERT_INVALID_LEN, length);
        }
        buffer.write(bytes, start + length, bytes.length - start - length);
        return buffer.toByteArray();
    }

    @Override
    public final String getString() throws Exception {
        if (isNull()) {
            return null;
        }
        String str = param1.getString();
        int start = Math.min(Math.max(0, param2.getInt() - 1), str.length());
        int length = Math.min(param3.getInt(), str.length());
        StringBuilder buffer = new StringBuilder();
        buffer.append(str.substring(0, start));
        buffer.append(param4.getString());
        if (length < 0) {
            throw MoonException.create(MoonCode.INSERT_INVALID_LEN, length);
        }
        buffer.append(str.substring(start + length));
        return buffer.toString();
    }

    @Override
    public int getPrecision() {
        return param1.getPrecision() + param2.getPrecision();
    }

}
